'''
#
# File: ut_model.py
# Description: Unit tests for JHB Model classes
#
# Copyright 2012 Adam Meadows
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
'''

import unittest
import random

from errors import DuplicateNameError, InvalidNameError, BalanceError
from model import Account, Category

class AccountTest(unittest.TestCase):
    def _setup_categories(self):
        for i in xrange(1, 20):
            c = self.account.add_category(name='Category %s' % i)
            c.balance = random.randint(0, 100000) / 100.0

    def setUp(self):
        self.account = Account(name='Checking', description='Chase')

    def test_create_account(self):
        '''Create a new account (with no categories)'''
        self.assertEquals('Checking', self.account.name)
        self.assertEquals('Chase', self.account.description)
        self.assertEquals(0, len(self.account.get_categories()))

    def test_get_category(self):
        '''Retrieve categories by name'''
        name = 'Category 1'
        self.assertRaises(InvalidNameError, self.account.get_category, name)
        self.account.add_category(name=name)
        self.assertEquals(1, len(self.account.get_categories()))
        c = self.account.get_category(name)
        self.assertEquals(c.name, name)

    def test_add_duplicate_category(self):
        '''Try to add duplicate category name'''
        name = 'Category 1'
        self.account.add_category(name=name)
        self.assertRaises(DuplicateNameError, self.account.add_category, name)

    def test_category_order(self):
        '''Make sure categories are returned in order'''
        self.account.add_category('Baby')
        self.account.add_category('Movies')
        self.account.add_category('Food')
        self.account.add_category('Gas')

        expected = ['Baby', 'Food', 'Gas', 'Movies']
        actual = [ c.name for c in self.account.get_categories() ]
        self.assertEquals(expected, actual)

    def test_get_balance(self):
        '''Make sure Account balance is sum of categories'''
        self._setup_categories()
        expected = sum(c.balance for c in self.account.category_dict.values())
        self.assertEquals(expected, self.account.get_balance())

    def test_filter_active_categories(self):
        '''Make sure you can filter out inactive Categories'''
        a = self.account
        baby = a.add_category('Baby')
        movies = a.add_category('Movies')
        food = a.add_category('Food')
        gas = a.add_category('Gas')

        movies.deactivate()
        gas.deactivate()

        expected = ['Baby', 'Food']
        actual = [ c.name for c in a.get_categories() ]
        self.assertEquals(expected, actual)

        expected = ['Baby', 'Food', 'Gas', 'Movies']
        actual = [ c.name for c in a.get_categories(active_only=False) ]
        self.assertEquals(expected, actual)

class CategoryTest(unittest.TestCase):
    def setUp(self):
        self.category = Category(name='Food')

    def test_deactivate(self):
        '''Deactivate a category'''
        self.assertTrue(self.category.is_active())
        self.category.deactivate()
        self.assertFalse(self.category.is_active())

    def test_deactivate_with_balance(self):
        '''Try to deactivate a Category with non-zero balance'''
        self.category.balance = 100.00
        self.assertRaises(BalanceError, self.category.deactivate)

    def test_activate(self):
        '''Make sure you can re-activate a deactivated Category'''
        self.category.deactivate()
        self.assertFalse(self.category.is_active())
        self.category.activate()
        self.assertTrue(self.category.is_active())

if __name__ == '__main__':
    unittest.main()

